/*
 * @(#)RegistryQueryService.java
 * Date 2013-08-13
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.service.es;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import javax.enterprise.inject.Alternative;

import javax.inject.Inject;

import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryRequest;

import org.apache.commons.lang3.ArrayUtils;

import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.TermsQueryBuilder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.exception.ServiceActionException;

import us.hornerscorners.lamppost.ihecommon.service.ElasticSearchSource;

import us.hornerscorners.lamppost.model.common.InstanceIdentifier;

import us.hornerscorners.lamppost.model.document.DocumentEntry;
import us.hornerscorners.lamppost.model.document.Folder;
import us.hornerscorners.lamppost.model.document.SubmissionSet;

import us.hornerscorners.lamppost.registry.constant.QueryField;

import us.hornerscorners.lamppost.registry.model.QueryRequest;

import us.hornerscorners.lamppost.registry.query.es.IQueryRunnerFactory;
import us.hornerscorners.lamppost.registry.query.es.QueryRunnerFactory;

import us.hornerscorners.lamppost.registry.service.IRegistryQueryService;

import us.hornerscorners.lamppost.registry.transformer.model.QueryRequestTransformer;

import us.hornerscorners.lamppost.transformer.ITransformer;


/**
 *
 * @author jim
 */
@ApplicationScoped
@Alternative
public class RegistryQueryService extends AbstractStoredQueryService
        implements IRegistryQueryService {

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /** Field description */
    @Inject
    private QueryRequestTransformer queryRequestTransformer;

    /** Field description */
    @Inject
    private QueryRunnerFactory queryRunnerFactory;

    /** Field description */
    @Inject
    private ElasticSearchSource source;

    /**
     * Constructs ...
     *
     */
    public RegistryQueryService() {
        super();
    }

    /**
     * Method description
     *
     *
     * @return
     */
    @Override
    protected ITransformer<AdhocQueryRequest, QueryRequest> getQueryRequestTransformer() {

        return this.queryRequestTransformer;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    @Override
    protected IQueryRunnerFactory getQueryRunnerFactory() {

        return this.queryRunnerFactory;
    }

    /**
     * Method description
     *
     *
     * @param entryURNs
     *
     * @return
     *
     * @throws ServiceActionException
     */
    @Override
    public DocumentEntry[] retrieveDocumentEntries(Collection<String> entryURNs)
            throws ServiceActionException {

        TermsQueryBuilder query =
            QueryBuilders.termsQuery(QueryField.DocumentEntryEntryUUID.getField(),
                                     entryURNs);

        List<DocumentEntry> result = this.source.runQuery(query, DocumentEntry.class);

        return result.toArray(new DocumentEntry[result.size()]);
    }

    /**
     * Method description
     *
     *
     * @param uniqueId
     *
     * @return
     *
     * @throws ServiceActionException
     */
    @Override
    public DocumentEntry retrieveDocumentEntry(InstanceIdentifier uniqueId)
            throws ServiceActionException {

        TermsQueryBuilder query =
            QueryBuilders.termsQuery(QueryField.DocumentEntryUniqueIdRoot.getField(),
                                     uniqueId.getRoot());

        List<DocumentEntry> results = this.source.runQuery(query, DocumentEntry.class);

        DocumentEntry result = null;

        if (results.isEmpty() == false) {

            result = results.get(0);
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param entryURN
     *
     * @return
     */
    @Override
    public DocumentEntry retrieveDocumentEntry(String entryURN)
            throws ServiceActionException {

        DocumentEntry result = null;
        DocumentEntry[] documentEntries =
            retrieveDocumentEntries(Collections.singletonList(entryURN));

        if (ArrayUtils.isNotEmpty(documentEntries)) {

            result = documentEntries[0];
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param entryURN
     *
     * @return
     */
    @Override
    public Folder retrieveFolder(String entryURN) throws ServiceActionException {

        Folder result = null;

        Folder[] folders = retrieveFolders(Collections.singletonList(entryURN));

        if (ArrayUtils.isNotEmpty(folders)) {

            result = folders[0];
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @param entryURNs
     *
     * @return
     *
     * @throws ServiceActionException
     */
    @Override
    public Folder[] retrieveFolders(Collection<String> entryURNs)
            throws ServiceActionException {

        TermsQueryBuilder query =
            QueryBuilders.termsQuery(QueryField.FolderEntryUUID.getField(), entryURNs);

        List<Folder> result = this.source.runQuery(query, Folder.class);

        return result.toArray(new Folder[result.size()]);
    }

    /**
     * Method description
     *
     *
     * @param entryURN
     *
     * @return
     *
     * @throws ServiceActionException
     */
    @Override
    public DocumentEntry[] retrieveRelatedDocuments(String entryURN)
            throws ServiceActionException {

        TermQueryBuilder query =
            QueryBuilders.termQuery(
                QueryField.DocumentEntryParentDocumentTargetEntryURN.getField(),
                entryURN);

        List<DocumentEntry> result = this.source.runQuery(query, DocumentEntry.class);

        return result.toArray(new DocumentEntry[result.size()]);
    }

    /**
     * Method description
     *
     *
     *
     * @param entryURN
     * @return
     */
    @Override
    public SubmissionSet retrieveSubmissionSet(String entryURN)
            throws ServiceActionException {

        SubmissionSet result = null;
        SubmissionSet[] subSets =
            retrieveSubmissionSets(Collections.singletonList(entryURN));

        if (ArrayUtils.isNotEmpty(subSets)) {

            result = subSets[0];
        }

        return result;
    }

    /**
     * Method description
     *
     *
     *
     * @param entryURNs
     * @return
     *
     * @throws ServiceActionException
     */
    @Override
    public SubmissionSet[] retrieveSubmissionSets(Collection<String> entryURNs)
            throws ServiceActionException {

        TermsQueryBuilder query =
            QueryBuilders.termsQuery(QueryField.SubmissionSetEntryUUID.getField(),
                                     entryURNs);

        List<SubmissionSet> result = this.source.runQuery(query, SubmissionSet.class);

        return result.toArray(new SubmissionSet[result.size()]);
    }
}
